package example

import (
	"image/color"
	"math"
	"time"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/canvas"
	"fyne.io/fyne/v2/container"
	"github.com/fogleman/ease"
	"github.com/tidwall/pinhole"
)

func PinHole(a fyne.App) {
	w := a.NewWindow("CPU based 3D rendering library: https://hub.fastgit.org/tidwall/pinhole")
	w.Resize(fyne.NewSize(900, 600))
	ww, hh := 300, 300
	p0 := pinhole.New()
	p0.DrawCube(-0.3, -0.3, -0.3, 0.3, 0.3, 0.3)
	p0.Rotate(math.Pi/3, math.Pi/6, 0)

	p0.Begin()
	p0.DrawCircle(0, 0, 0, 0.2)
	p0.Rotate(0, math.Pi/2, 0)
	p0.Translate(-0.6, -0.4, 0)
	p0.Colorize(color.RGBA{255, 0, 0, 255})
	p0.End()
	c0 := canvas.NewImageFromImage(p0.Image(ww, hh, nil))

	p := NewPinHole()
	p.DrawLine(-0.3, -0.3, -0.3, 0.3, 0.3, 0.3)
	p.DrawLine(-0.2, -0.3, 0, 0.3, 0.3, 0)
	p.DrawDot(0, 0, 0, 0.1)
	c1 := canvas.NewImageFromImage(p.Image(ww, hh, nil))

	p.Clear()
	p.DrawCircle(0, 0, 0, 0.2)
	p.Colorize(color.RGBA{255, 0, 0, 255})
	c2 := canvas.NewImageFromImage(p.Image(ww, hh, nil))
	r := 0.0
	go func() {
		for {
			p.DrawCircle(0, 0, 0, 0.2)
			p.Colorize(color.RGBA{255, 0, 0, 255})
			r = r + math.Pi/180
			p.Rotate(0, r, 0)
			c2.Image = p.Image(ww, hh, nil)
			c2.Refresh()
			p.Clear()
			time.Sleep(time.Millisecond * 10)
		}
	}()

	p3 := NewPinHole()
	c3 := canvas.NewImageFromImage(p3.Image(ww, hh, nil))
	x := -1.0
	go func() {
		for {
			p3.DrawDot(-1, 0, 0, 0.2)
			x = x + 0.01
			if x > 2 {
				x = -1
			}
			p3.Translate(x, 0, 0)
			p3.Image(ww, hh, nil)
			c3.Image = p3.Image(ww, hh, nil)
			c3.Refresh()
			p3.Clear()
			time.Sleep(time.Millisecond * 10)
		}
	}()
	c4 := canvas.NewImageFromImage(nil)
	go shapes(c4)

	c5 := canvas.NewImageFromImage(nil)
	go spiral(c5)

	c6 := canvas.NewImageFromImage(nil)
	go suzanne(c6)

	c7 := canvas.NewImageFromImage(nil)
	go gopher(c7)
	cc := canvas.NewCircle(color.Black)
	// c1.Position1=fyne.NewPos(10,10)
	// c1.Position2=fyne.NewPos(100,100)

	c := container.NewVScroll(container.NewGridWrap(fyne.NewSize(300, 300),
		cc, c0, c1, c2, c3, c4, c5, c6, c7))
	w.SetContent(c)
	w.CenterOnScreen()
	w.Show()
}

func shapes(img *canvas.Image) {
	n := 6000
	p := NewPinHole()
	//rotate := math.Pi / 3
	for i := 0; i < n; i++ {
		if i >= n-1 {
			i = 0
		}
		p.Clear()
		p.Begin()
		p.DrawCube(-0.2, -0.2, -0.2, 0.2, 0.2, 0.2)
		p.Rotate(0, math.Pi*2/(float64(n)/float64(i)), 0)
		p.Colorize(color.RGBA{255, 0, 0, 255})
		p.End()

		p.Begin()
		p.DrawCircle(0, 0, 0, 0.2)
		p.Rotate(math.Pi*2/(float64(n)/float64(i)), math.Pi*4/(float64(n)/float64(i)), 0)
		p.End()

		p.Begin()
		p.DrawCircle(0, 0, 0, 0.2)
		p.Rotate(-math.Pi*2/(float64(n)/float64(i)), math.Pi*4/(float64(n)/float64(i)), 0)
		p.End()

		p.Scale(1.75, 1.75, 1.75)

		img.Image = p.Image(300, 300, nil)
		img.Refresh()
		time.Sleep(time.Millisecond)
	}
}
func makeSpiral() *pinhole.Pinhole {
	p := pinhole.New()
	n := 360.0
	for i, z := 0.0, -0.2; i < n && z <= 1; i, z = i+1, z+0.003 {
		d := 0.5 * (1 - (i / n / 2))  // distance of circle from origin
		a := math.Pi * 2 / 30 * i     // angle of circle from origin
		r := 0.03 * (1 - (i / n / 2)) // radius of circle
		p.DrawCircle(math.Cos(a)*d, math.Sin(a)*d, z, r)
	}
	return p
}
func spiral(img *canvas.Image) {
	p := makeSpiral()
	n := 60
	rotate := math.Pi / 3
	for i := 0; i < n; i++ {
		if i >= n-1 {
			i = 0
		}
		t := float64(i) / float64(n)
		if t < 0.5 {
			t = ease.InSine(t * 2)
		} else {
			t = 1 - ease.OutSine((t-0.5)*2)
		}
		a := rotate * t
		p.Rotate(a, 0, 0)

		img.Image = p.Image(300, 300, nil)
		img.Refresh()
		time.Sleep(time.Microsecond)
		p.Rotate(-a, 0, 0)
	}

}
